/*
 * hdf5_rw.h
 *
 *  Created on: Apr 7, 2011
 *      Author: snirgaz
 */
#ifndef HDF5_RW_H_
#define HDF5_RW_H_
#include "def.h"
#include "H5Cpp.h"
using namespace H5;
using namespace std;

typedef vector<hsize_t> DimsHdf5;

class hdf5RW {
private:
	// File_id
	H5File file_;
public:
	hdf5RW();
	~hdf5RW();
	void initNew(string fileName);
	void initAppend(string fileName);
	void initRead(string fileName);
	void closeFile();
	template<class T>
	void writeComp(string dsName, DimsHdf5 dims, T const *data);
	template<class T>
	void read(string dsName, T *data);
	template<class T>
	void writeSingle(string dsName, T const data);
	template<class T>
	static DataType getHDF5DataType();
	DataSet openDataSet(string const & dsName);
	DataSet newDataSet(string const &dsName, DataType const &type,
			DataSpace const &space);
	Group CreateGroup(string const &dsName);
};

template<typename T>
void hdf5RW::writeSingle(string dsName, T const data) {
	DimsHdf5 dims(1, 1);
	T temp = data;
	this->writeComp<T>(dsName, dims, &temp);
}
template<typename T>
void hdf5RW::writeComp(string dsName, DimsHdf5 dims, T const *data) {
	try {
		Exception::dontPrint();
		DataType type = hdf5RW::getHDF5DataType<T>();
		// Dimensions
		int rank = dims.size();
		hsize_t *dimsP = &(dims[0]);
		DimsHdf5 cdims(dims.size(), 1);
		cdims.back() = dims.back();
		hsize_t *cdimsP = &(cdims[0]);
		// Property List
		int fillvalue = 0; /* Fill value for the dataset */
		DSetCreatPropList plist = DSetCreatPropList(H5P_DATASET_CREATE);
		plist.setFillValue(type, &fillvalue);
		plist.setChunk(rank, cdimsP);
		plist.setDeflate(9);
		// Data Space
		DataSpace space(rank, dimsP);
		DataSet dataset = DataSet(
				file_.createDataSet(dsName.c_str(), type, space, plist));
		dataset.write(data, type, space, space);
	} // end of try block
	  // catch failure caused by the DataSet operations
	catch (DataSetIException error) {
		error.printError();
		exit(-1);
	}
	// catch failure caused by the DataSpace operations
	catch (DataSpaceIException error) {
		error.printError();
		exit(-1);
	}
}
template<typename T>
void hdf5RW::read(string dsName, T *data) {
	try {
		DataType type = hdf5RW::getHDF5DataType<T>();
		DataSet dataset = file_.openDataSet(dsName.c_str());
		DataSpace dataspace = dataset.getSpace();
		dataset.read(data, type, dataspace, dataspace);
		// catch failure caused by the DataSet operations
	} catch (DataSetIException error) {
		error.printError();
		exit(-1);
	}
	// catch failure caused by the DataSpace operations
	catch (DataSpaceIException error) {
		error.printError();
		exit(-1);
	}

}
#endif // HDF5_RW

